package server

import (
	"context"
	"strings"

	"gitee.com/crack007/goose/gscore"
	"gitee.com/crack007/goose/gsutil"
	"github.com/spf13/cobra"
)

type ServerBuilder struct {
	Port           uint16
	Host           string
	protocol       string
	serverName     string
	SessionBuilder *SessionBuilder
	Handle         IServerHandle
	gscore.BaseBuilder
}

func NewServerBuilder(iServerHandle IServerHandle, sessionBuilder *SessionBuilder) *ServerBuilder {
	ctx, cancelFunc := context.WithCancel(context.Background())
	return &ServerBuilder{
		Handle:         iServerHandle,
		SessionBuilder: sessionBuilder,
		Host:           "",
		protocol:       Server_Tcp,
		BaseBuilder: gscore.BaseBuilder{
			Ctx:        ctx,
			CancelFunc: cancelFunc,
			CobraCmd:   &cobra.Command{},
		},
	}
}

func (x *ServerBuilder) SetProtocol(protocol string) {
	x.protocol = protocol
}

func (x *ServerBuilder) SetHost(Host string) {
	x.Host = Host
}

func (x *ServerBuilder) SetPort(Port uint16) {
	x.Port = Port
}

func (x *ServerBuilder) SetServerName(serverName string) {
	x.serverName = serverName
}

func (x *ServerBuilder) Build() (gscore.IServer, error) {
	_sessionManager := NewSessionManager()
	serverInstance := &Server{
		Host:           x.Host,
		Port:           x.Port,
		Network:        x.protocol,
		handle:         nil,
		sessionBuilder: x.SessionBuilder,
		BaseServer: gscore.BaseServer{
			IsGraceful: true,
			Ctx:        x.GetCtx(),
			Cancel:     x.GetCancelFunc(),
			WorkPath:   gsutil.RuntimeUtil.GetWorkPath(),
		},
		SessionManager: _sessionManager,
		MessageManager: NewMessageManager(_sessionManager, x.SessionBuilder, x.GetCtx()),
		isUnix:         strings.ToLower(x.protocol) == Server_Unix,
		Builder:        x,
	}
	serverInstance.SetServerName(x.serverName)
	serverInstance.SetCobraCmd(x.GetCobraCmd())
	return serverInstance, nil
}

func (x *ServerBuilder) GetHandle() gscore.IHandle {
	return x.Handle
}

func (x *ServerBuilder) EnablePortFlag(defaultPort uint16) *ServerBuilder {
	x.GetCobraCmd().PersistentFlags().Uint16VarP(&x.Port, "port", "p", defaultPort, "tcp/udp server listen port")
	return x
}
